package com.xue.domain;

import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import io.netty.buffer.ByteBuf;
import lombok.Getter;
import lombok.Setter;

import java.net.InetSocketAddress;
import java.nio.charset.StandardCharsets;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author xuejingbao
 * @create 2022-08-02 10:45
 */
@Getter
@Setter
public abstract class Info {

    private transient InetSocketAddress sender;

    public Info() {
    }

    public abstract Integer getInfoType();

    public static final byte FRAME_HEADER = 5;
    public static final byte MAGIC = 0x66;

    public static final Integer LOCATION_INFO = 1;
    public static final Integer LOCATION_LIGHT_INFO = 2;
    public static final Integer STATIC_LOCATION_INFO_REQUEST = 12;
    public static final Integer STATIC_LOCATION_INFO_RESPONSE = 13;
    public static final Integer STATIC_LOCATION_LIGHT_INFO = 14;
    public static final Integer AREA_INFO = 15;


    private static final Map<Integer, Class<? extends Info>> infoClasses = new ConcurrentHashMap<>();

    static {
        infoClasses.put(LOCATION_INFO, LocationInfo.class);
        infoClasses.put(LOCATION_LIGHT_INFO, LocationLightInfo.class);
        infoClasses.put(STATIC_LOCATION_INFO_REQUEST, StaticLocationRequestInfo.class);
        infoClasses.put(STATIC_LOCATION_INFO_RESPONSE, StaticLocationResponseInfo.class);
        infoClasses.put(STATIC_LOCATION_LIGHT_INFO, StaticLocationLightInfo.class);
        infoClasses.put(AREA_INFO, AreaInfo.class);
    }

    /**
     * 根据消息类型字节，获得对应的消息 class
     *
     * @param infoType 消息类型字节
     * @return 消息 class
     */
    public static Class<? extends Info> getInfoClass(Integer infoType) {
        return infoClasses.get(infoType);
    }

    /**
     * 编码器
     *
     * @param byteBuf
     * @return
     */
    public ByteBuf encoding(ByteBuf byteBuf) {
        byteBuf.writeByte(Info.MAGIC);
        JSONObject jsonObject = JSONUtil.parseObj(this);
        if (jsonObject.isEmpty()) {
            byteBuf.writeShort(Info.FRAME_HEADER);
            byteBuf.writeShort(getInfoType());
        } else {
            byte[] bytes = jsonObject.toString().getBytes(StandardCharsets.UTF_8);
            byteBuf.writeShort(bytes.length + Info.FRAME_HEADER);
            byteBuf.writeShort(getInfoType());
            byteBuf.writeBytes(bytes);
        }
        return byteBuf;
    }

    /**
     * 解码器
     *
     * @param content
     * @return
     */
    public Info decoding(ByteBuf content) {
        byte[] date = new byte[content.readableBytes()];
        content.readBytes(date);
        return JSONUtil.toBean(new String(date, StandardCharsets.UTF_8), this.getClass());
    }

}
